package com.example.tms.common.aop;

import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.util.Optional;
import java.util.stream.Collectors;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.JsonNode;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.example.tms.common.annotation.LogAction;
import com.example.tms.entity.Employee;
import com.example.tms.entity.SystemLog;
import com.example.tms.mapper.SystemLogMapper;
import com.example.tms.util.JwtTokenUtil;

import jakarta.servlet.http.HttpServletRequest;


@Aspect
@Component
public class LogAspect {
    private static final Logger log = LogManager.getLogger(LogAspect.class);

    @Autowired
    private SystemLogMapper systemLogMapper;
    
    @Autowired
    private JwtTokenUtil jwtTokenUtil;
    
    @Autowired
    private UserDetailsService userDetailsService;

//     拦截所有Controller方法
    @Pointcut("execution(public * com.example.tms.controller..*.*(..)) && " +
            "@within(org.springframework.web.bind.annotation.RestController) && " +
            "!execution(* com.example.tms.controller.AuthController.login(..))")
    public void controllerPointcut() {}


    // 成功日志记录
    @AfterReturning(pointcut = "controllerPointcut()", returning = "result")
    public void logAfterReturning(JoinPoint joinPoint, Object result) {
        log.debug("AOP拦截到方法: {}", joinPoint.getSignature());
        saveLog(joinPoint, "INFO", "操作成功");
    }

    // 异常日志记录
    @AfterThrowing(pointcut = "controllerPointcut()", throwing = "e")
    public void logAfterThrowing(JoinPoint joinPoint, Exception e) {
        saveLog(joinPoint, "ERROR", e.getMessage());
    }

    private void saveLog(JoinPoint joinPoint, String defaultLevel, String message) {

        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();

        // 获取注解配置
        LogAction logAction = method.getAnnotation(LogAction.class);
        String action = logAction != null ? logAction.value() : joinPoint.getSignature().getName();
        String level = logAction != null ? logAction.level() : defaultLevel;

        SystemLog systemLog = new SystemLog();
        systemLog.setLevel(level);
        systemLog.setAction(action);
        systemLog.setUserId(getCurrentUserId()); // 需实现获取当前用户ID
        systemLog.setIp(getCurrentIp()); // 需实现获取当前IP
        systemLog.setCreatedAt(LocalDateTime.now().toString());

        systemLogMapper.insert(systemLog);
        log.info("已记录操作日志到数据库: {}", systemLog);
    }

    // 获取当前用户ID
    private String getCurrentUserId() {
        HttpServletRequest request = ((ServletRequestAttributes)
                RequestContextHolder.getRequestAttributes()).getRequest();
        String authHeader = request.getHeader("Authorization");
        
        if (authHeader != null && authHeader.startsWith("Bearer ")) {
            try {
                String token = authHeader.substring(7);
                String userId = jwtTokenUtil.extractUsername(token);
                if (userId != null && !userId.isEmpty()) {
                    return userId;
                }
            } catch (Exception e) {
                log.error("Failed to extract user ID from token", e);
            }
        }
        return "1";
    }

    // 获取当前IP
//    private String getCurrentIp() {
//        return Optional.ofNullable(MDC.get("ip")).orElse("0.0.0.0");    }

    private String getCurrentIp() {
        HttpServletRequest request = ((ServletRequestAttributes)
                RequestContextHolder.getRequestAttributes()).getRequest();

        return Optional.ofNullable(request.getHeader("X-Forwarded-For"))
                .map(xff -> xff.split(",")[0].trim())
                .orElse(request.getRemoteAddr());
    }
}
